package com.launch.imscore.filter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 说明：IP白名单
 *
 * @author zhongboWork
 * @version 1.0
 * @date 2022-01-04 20:09
 */
@Component
public class IpFilter implements Filter {
    private Logger log = LoggerFactory.getLogger(IpFilter.class);

    @Value("${ip.pwd}")
    private String ipPwd = "123456";
    @Value("${ip.admin}")
    private String ipAdmin = "ipAdmin";
    @Value("${ip.config.file}")
    private String ipConfigFile = "ipAdmin.json";
    private List<String> whiteIpList = new ArrayList<String>();
    private String separator = File.separator;

    @PostConstruct
    public void init() {
        File file = getConfigFile();
        whiteIpList = loadJson(file);
    }

    private File getConfigFile() {
        String userDir = System.getProperty("user.dir");
        return new File(userDir + separator + ipConfigFile);
    }

    private List<String> loadJson(File file) {
        List<String> list = new ArrayList<String>();
        if (file.exists()) {
            if (file.isFile()) {
                ObjectMapper objectMapper = new ObjectMapper();
                try {
                    TypeReference<List<String>> listTypeReference = new TypeReference<List<String>>() {
                    };
                    list = objectMapper.readValue(file, listTypeReference);
                    log.info("loadJson: {}, {}", file, list);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                File file1 = new File(file.getAbsolutePath() + separator + ipConfigFile);
                int maxDeep = 99;
                String uuid = UUID.randomUUID().toString();
                if (file1.getAbsolutePath().replace(separator, uuid).split(uuid).length > maxDeep) {
                    log.error("tooDeepConfigFile!{}, {}", maxDeep, file1);
                } else {
                    loadJson(file1);
                }
            }
        }
        return list;
    }

    private void writeJson(List<String> list, File file) {
        ObjectMapper objectMapper = new ObjectMapper();
        boolean mkdirs = file.getParentFile().mkdirs();
        if (file.isFile() || !file.exists()) {
            try {
                objectMapper.writeValue(file, list);
                log.info("writeJson: {}, {}", file, list);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            File file1 = new File(file.getAbsolutePath() + separator + ipConfigFile);
            int maxDeep = 99;
            String uuid = UUID.randomUUID().toString();
            if (file1.getAbsolutePath().replace(separator, uuid).split(uuid).length > maxDeep) {
                log.error("tooDeepConfigFile!{}, {}", maxDeep, file1);
            } else {
                writeJson(list, file1);
            }
        }
    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String ipAdmin = request.getParameter(this.ipAdmin);
        String remoteAddr = request.getRemoteAddr();
        if (whiteIpList.contains(remoteAddr) && ipAdmin == null) {
            chain.doFilter(servletRequest, servletResponse);
            return;
        }
        StringBuilder sb = new StringBuilder();
        sb.append("<hr>");
        String pwd = request.getParameter("pwd");
        if (!ipPwd.equals(pwd)) {
            sb.append("<form method='POST' enctype='multipart/form-data'>\n")
                    .append("<span>禁止").append(remoteAddr).append("访问</span>\n")
                    .append("<input type='text' name='pwd'>\n")
                    .append("<button type='submit'>管理</button>\n")
                    .append("</form>\n");
        } else {
            String ip = request.getParameter("ip");
            String del = request.getParameter("del");
            if (del != null) {
                whiteIpList.remove(del);
                File file = getConfigFile();
                writeJson(whiteIpList, file);
            }
            if (ip != null && !whiteIpList.contains(ip)) {
                whiteIpList.add(ip);
                File file = getConfigFile();
                writeJson(whiteIpList, file);
            }
            sb.append("<ul>\n");
            for (String whiteIp : whiteIpList) {
                //<li><a href="?get=%s" target="_blank">%s</a></li>\n
                String delPost = "<form method='POST' enctype='multipart/form-data'>\n" +
                        "<span>" + whiteIp + "</span>\n" +
                        "<input type='hidden' name='del' value='" + whiteIp + "'>\n" +
                        "<input type='hidden' name='pwd' value='" + pwd + "'>\n" +
                        "<input type='hidden' name='" + this.ipAdmin + "'>\n" +
                        "<button type='submit'>删除</button>\n" +
                        "</form>\n";
                String aEle = String.format("<li>%s</li>\n", delPost);
                sb.append(aEle);
            }
            sb.append("</ul>\n");
            String ban = "<span>禁止" + remoteAddr + "访问</span>\n";
            if (whiteIpList.contains(remoteAddr)) {
                ban = "<a href>访问</a>\n";
            }
            sb.append("<form method='POST' enctype='multipart/form-data'>\n")
                    .append(ban)
                    .append("<input type='hidden' name='pwd' value='")
                    .append(pwd)
                    .append("'>\n")
                    .append("<input type='text' name='ip'>\n")
                    .append("<button type='submit'>添加</button>\n")
                    .append("</form>\n");
        }
        response.setContentType(MediaType.TEXT_HTML.toString());
        response.setCharacterEncoding(Charset.defaultCharset().toString());
        PrintWriter writer = response.getWriter();
        writer.write(sb.toString());
        writer.close();
    }
}
